package com.runccyy.service.impl;

import com.runccyy.dao.mapper.RunRecordMapper;
import com.runccyy.dao.mapper.UserMapper;
import com.runccyy.dao.model.RunRecordPO;
import com.runccyy.dao.model.RunRecordStatPO;
import com.runccyy.dao.model.StepInfo;
import com.runccyy.dao.model.UserPO;
import com.runccyy.service.RunRecordService;
import com.runccyy.service.model.RunRecordStatBO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class RunRecordServiceImpl implements RunRecordService {

    @Resource
    private RunRecordMapper runRecordMapper;

    @Resource
    private UserMapper userMapper;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public int insertOrUpdateRunRecord(List<RunRecordPO> runRecords) {
        int affectedRows = 0;
        for (RunRecordPO record : runRecords) {
            RunRecordPO existingRecord = runRecordMapper.selectRunRecordByUserIdAndDate(record.getUserId(), record.getDate());
            if (existingRecord!= null) {
                record.setId(existingRecord.getId());
                affectedRows += runRecordMapper.updateRunRecord(record);
            } else {
                affectedRows += runRecordMapper.insertRunRecord(record);
            }
        }
        return affectedRows;
    }


    @Override
    public RunRecordPO getRunRecordByUserIdAndDate(Long userId, Long date) {
        return runRecordMapper.selectRunRecordByUserIdAndDate(userId, date);
    }

    @Override
    public List<RunRecordStatBO> countDaysRank(Long startTime, Long endTime) {
        List<RunRecordStatPO> runRecordStatPOS = runRecordMapper.countDaysWithStepCntGreaterThanOrEqualFiveThousand(startTime, endTime);
        if (CollectionUtils.isEmpty(runRecordStatPOS)){
            return new ArrayList<>();
        }
        List<Long> userIds = runRecordStatPOS.stream().map(RunRecordStatPO::getUserId).collect(Collectors.toList());
        List<UserPO> users= userMapper.getByUserIds(userIds);
        Map<Long, String> userMap = users.stream().collect(Collectors.toMap(UserPO::getId, UserPO::getName));
        return runRecordStatPOS.stream().map(item ->{
            RunRecordStatBO runRecordStatBO = new RunRecordStatBO();
            runRecordStatBO.setUserId(item.getUserId());
            runRecordStatBO.setDays(item.getDays());
            runRecordStatBO.setTotalStepCnt(item.getTotalStepCnt());
            runRecordStatBO.setName(userMap.get(item.getUserId()));
            return runRecordStatBO;
        }).collect(Collectors.toList());
    }

    @Override
    public List<RunRecordStatBO> sumStepCntRank(Long startTime, Long endTime) {
        List<RunRecordStatPO> runRecordStatPOS = runRecordMapper.sumStepCntByUserId(startTime, endTime);
        if (CollectionUtils.isEmpty(runRecordStatPOS)){
            return new ArrayList<>();
        }
        List<Long> userIds = runRecordStatPOS.stream().map(RunRecordStatPO::getUserId).collect(Collectors.toList());
        List<UserPO> users= userMapper.getByUserIds(userIds);
        Map<Long, String> userMap = users.stream().collect(Collectors.toMap(UserPO::getId, UserPO::getName));
        return runRecordStatPOS.stream().map(item ->{
            RunRecordStatBO runRecordStatBO = new RunRecordStatBO();
            runRecordStatBO.setUserId(item.getUserId());
            runRecordStatBO.setDays(item.getDays());
            runRecordStatBO.setTotalStepCnt(item.getTotalStepCnt());
            runRecordStatBO.setName(userMap.get(item.getUserId()));
            return runRecordStatBO;
        }).collect(Collectors.toList());
    }

    @Override
    public StepInfo queryStepInfo(Long userId) {
        LocalDateTime startDateTime = LocalDateTime.of(2025, 1, 10, 0, 0, 0);
        // 获取 2025 年 2 月 9 日 23 点 0 分 0 秒的 LocalDateTime 对象
        LocalDateTime endDateTime = LocalDateTime.of(2025, 2, 9, 23, 59, 59);
        // 将 LocalDateTime 转换为秒级时间戳
        long startTimeStamp = startDateTime.toEpochSecond(ZoneOffset.ofHours(8));
        long endTimeStamp = endDateTime.toEpochSecond(ZoneOffset.ofHours(8));
        Long currenDateTime = getCurrenDateTime();
        Long totalRunCnt = runRecordMapper.queryTotalRunCnt(userId,startTimeStamp,endTimeStamp);
        Long currentStepCnt = runRecordMapper.currentStepCnt(userId, currenDateTime);
        StepInfo stepInfo = new StepInfo();
        stepInfo.setCurrentStepCnt(currentStepCnt);
        stepInfo.setTotalRunDays(totalRunCnt);
        return stepInfo;
    }

    private Long getCurrenDateTime(){
        LocalDate localDate = LocalDate.now();
        // 创建一个代表 0 点 0 分 0 秒的 LocalTime 对象
        LocalTime localTime = LocalTime.of(0, 0, 0);
        // 将日期和时间组合起来
        LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
        // 转换为秒级时间戳
        return localDateTime.toEpochSecond(ZoneOffset.ofHours(8));
    }
}
